package rxbonjour.broadcast; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import java.net.InetAddress; import javax.jmdns.JmDNS; import javax.jmdns.ServiceInfo; import javax.jmdns.impl.DNSStatefulObject; import rx.observers.TestSubscriber; import rxbonjour.base.BaseTest; import rxbonjour.exc.StaleContextException; import rxbonjour.model.BonjourEvent; import static junit.framework.Assert.assertEquals; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; @PrepareForTest({ JmDNS.class, SupportBonjourBroadcast.class }) public class SupportBonjourBroadcastTest extends BaseTest { private TestJmDNS jmdns; abstract class TestJmDNS extends JmDNS implements DNSStatefulObject { } @Override protected void setupMocks() throws Exception { WifiManager wifiManager = mock(WifiManager.class); WifiInfo wifiInfo = mock(WifiInfo.class); WifiManager.MulticastLock lock = mock(WifiManager.MulticastLock.class); jmdns = mock(TestJmDNS.class); // Wire default return values when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager); when(wifiManager.createMulticastLock(anyString())).thenReturn(lock); when(wifiInfo.getIpAddress()).thenReturn(0); when(wifiManager.getConnectionInfo()).thenReturn(wifiInfo); // Mock statics mockStatic(JmDNS.class); // Wire statics given(JmDNS.create(any(InetAddress.class), anyString())).willReturn(jmdns); } private void setJmDNSMockClosed() { when(jmdns.isClosing()).thenReturn(true); when(jmdns.isClosed()).thenReturn(true); } @Test public void testAddAndRemoveOneCycle() throws Exception { BonjourBroadcastBuilder builder = PowerMockito.spy(SupportBonjourBroadcast.newBuilder("_http._tcp")); BonjourBroadcast<?> broadcast = builder.build(); TestSubscriber<BonjourEvent> subscriber = new TestSubscriber<>(); ArgumentCaptor<ServiceInfo> captor = ArgumentCaptor.forClass(ServiceInfo.class); broadcast.start(context).subscribe(subscriber); subscriber.assertNoErrors(); verify(jmdns, times(1)).registerService(captor.capture()); ServiceInfo serviceInfo = captor.getValue(); assertEquals(serviceInfo.getType(), "_http._tcp.local."); subscriber.unsubscribe(); verify(jmdns, times(1)).unregisterService(serviceInfo); verify(jmdns, times(1)).close(); setJmDNSMockClosed(); } @Test public void testAddAndRemoveOneCycleWithLocalDomain() throws Exception { BonjourBroadcastBuilder builder = PowerMockito.spy(SupportBonjourBroadcast.newBuilder("_http._tcp.local.")); BonjourBroadcast<?> broadcast = builder.build(); TestSubscriber<BonjourEvent> subscriber = new TestSubscriber<>(); ArgumentCaptor<ServiceInfo> captor = ArgumentCaptor.forClass(ServiceInfo.class); broadcast.start(context).subscribe(subscriber); subscriber.assertNoErrors(); verify(jmdns, times(1)).registerService(captor.capture()); ServiceInfo serviceInfo = captor.getValue(); assertEquals(serviceInfo.getType(), "_http._tcp.local."); subscriber.unsubscribe(); verify(jmdns, times(1)).unregisterService(serviceInfo); verify(jmdns, times(1)).close(); setJmDNSMockClosed(); } @Test public void testAddAndRemoveTwoDifferentBroadcast() throws Exception { BonjourBroadcastBuilder bd1 = PowerMockito.spy(SupportBonjourBroadcast.newBuilder("_http._tcp")); BonjourBroadcast<?> bc1 = bd1.build(); BonjourBroadcastBuilder bd2 = PowerMockito.spy(SupportBonjourBroadcast.newBuilder("_ftp._tcp")); BonjourBroadcast<?> bc2 = bd2.build(); TestSubscriber<BonjourEvent> subscriber1 = new TestSubscriber<>(); TestSubscriber<BonjourEvent> subscriber2 = new TestSubscriber<>(); ArgumentCaptor<ServiceInfo> captor = ArgumentCaptor.forClass(ServiceInfo.class); bc1.start(context).subscribe(subscriber1); subscriber1.assertNoErrors(); verify(jmdns, times(1)).registerService(captor.capture()); ServiceInfo si1 = captor.getValue(); assertEquals(si1.getType(), "_http._tcp.local."); bc2.start(context).subscribe(subscriber2); subscriber2.assertNoErrors(); verify(jmdns, times(2)).registerService(captor.capture()); ServiceInfo si2 = captor.getValue(); assertEquals(si2.getType(), "_ftp._tcp.local."); subscriber1.unsubscribe(); verify(jmdns, times(1)).unregisterService(si1); verify(jmdns, never()).close(); subscriber2.unsubscribe(); verify(jmdns, times(1)).unregisterService(si2); verify(jmdns, times(1)).close(); setJmDNSMockClosed(); } @Test public void testStaleContext() throws Exception { BonjourBroadcastBuilder builder = PowerMockito.spy(SupportBonjourBroadcast.newBuilder("_http._tcp.local.")); BonjourBroadcast<?> broadcast = builder.build(); TestSubscriber<BonjourEvent> subscriber = new TestSubscriber<>(); broadcast.start(null).subscribe(subscriber); subscriber.assertError(StaleContextException.class); } }